private import base;
private import casting;
private import strings;

-- dates and time

type date is date(_long) or never;

implementation coercion over (date,string) is {
  coerce(date(D)) is string(__date_string(D));
  coerce(never) is "never"
}

implementation coercion over (string,date) is {
  coerce(string(S)) is date(__string_date(S)) default never;
}

implementation coercion over (date, long) is {
  coerce(date(D)) is long(D);
  coerce(never) is nonLong;
}

implementation coercion over (long,date) is {
  coerce(long(D)) is date(D);
  coerce(nonLong) is never;
}

implementation formatting over date is {
  _format(date(D),string(F)) is ppStr(string(__format_date(D,F)));
}

parse_date(string(S),string(F)) is date(__parse_date(S,F));

format_date(date(D),string(F)) is string(__format_date(D,F));
format_date(never,_) is "never";

implementation pPrint over date is {
  ppDisp(D) is ppStr(D as string)
}

implementation comparable over date is {
  date(X)<date(Y) is __long_lt(X,Y);
  _ < _ default is false;
  date(X)<=date(Y) is __long_le(X,Y);
  _ <= _ default is false;
  date(X)>date(Y) is __long_gt(X,Y);
  _ > _ default is false;
  date(X)>=date(Y) is __long_ge(X,Y);
  _ >= _ default is false;
}

implementation largeSmall over date is {
  largest is date(0x7fffffffffffffffL_);
  smallest is date(0x0L_);
}

now() is date(_now());

today() is date(_today());

timeDiff(date(F),date(T)) is long(__long_minus(F,T));
timeDiff(never,_) is nonLong;
timeDiff(_,never) is nonLong;

timeDelta(date(T),long(D)) is date(__long_plus(T,D));
timeDelta(never,_) is never;